<template>
	<div style="height: 100%">
		<cl-pagefull @resize="onResize">
			<template #head>
				<slot name="head" />
			</template>
			<cl-flex1 ref="box" style="height: 100%; overflow: hidden">
				<el-table
					class="data-table"
					ref="table"
					v-on="$listeners"
					v-bind="tablePrpos"
					:data="list"
					v-loading="loading"
					:max-height="full ? clientHeight : null"
				>
					<vnodes :vnodes="renderColumns()" />
					<slot slot="append" name="append" />
					<slot slot="empty" name="empty">
						<cl-empty :tips="emptyText" />
					</slot>
				</el-table>
			</cl-flex1>
			<template #foot>
				<div class="table-footer" v-if="showPage">
					<el-pagination
						v-bind="pagePrpos"
						@size-change="sizeChange"
						@current-change="currentChange"
					/>
				</div>
			</template>
		</cl-pagefull>
	</div>
</template>
<script>
import { Table, Pagination } from "element-ui";
import { get } from "lodash";
function pagination(pageNo, pageSize, list) {
	var offset = (pageNo - 1) * pageSize;
	return offset + pageSize >= list.length
		? list.slice(offset, list.length)
		: list.slice(offset, offset + pageSize);
}
const pageProps = Pagination.props;
export default {
	name: "cl-data-table",
	props: {
		...Table.props,
		full: {
			type: Boolean,
			default: false
		},
		loading: {
			type: Boolean,
			default: false
		},
		showPage: {
			type: Boolean,
			default: true
		},
		autoPage: {
			type: Boolean,
			default: false
		},
		stripe: {
			type: Boolean,
			default: true
		},
		border: {
			type: Boolean,
			default: true
		},
		total: pageProps.total,
		page: pageProps.currentPage,
		limit: pageProps.pageSize,
		hideOnSinglePage: pageProps.hideOnSinglePage,
		pageLayout: {
			type: String,
			default: "total,sizes,prev,pager,next,jumper"
		},
		pageSizes: {
			type: Array,
			default: () => [10, 20, 30, 40, 50, 100, 500]
		},
		columns: {
			default: () => [],
			type: Array
		},
		resetPage: {
			type: Boolean,
			default: true
		}
	},
	components: {
		Vnodes: {
			name: "vnodes",
			functional: true,
			render: (h, ctx) => ctx.props.vnodes
		}
	},
	data() {
		return {
			pageSize: this.limit,
			currentPage: this.page,
			clientHeight: 0
		};
	},
	watch: {
		page(v) {
			this.currentPage = v;
		},
		limit(v) {
			this.pageSize = v;
		},
		loading(v) {
			// 修复重新请求接口时，不重置回第一页
			if (v && this.resetPage) {
				this.currentChange(1);
			}
		}
	},
	computed: {
		list() {
			const { data, autoPage, currentPage, pageSize } = this;
			if (autoPage) {
				return pagination(currentPage, pageSize, data);
			}
			return data;
		},
		tablePrpos() {
			const props = this.$props;
			return Object.keys(Table.props).reduce(
				(prev, curr) => {
					prev[curr] = props[curr];
					return prev;
				},
				{ stripe: true }
			);
		},
		pagePrpos() {
			const props = this.$props;
			let result = Object.keys(pageProps).reduce((prev, curr) => {
				prev[curr] = props[curr];
				return prev;
			}, {});
			return {
				...result,
				total: this.autoPage ? this.data.length : this.total,
				currentPage: this.page,
				pageSize: this.limit,
				layout: this.pageLayout,
				background: true
			};
		}
	},
	methods: {
		renderColumns() {
			const deep = (list, pIndex) => {
				return list.map((item, idx) => {
					let key = `${pIndex}-${idx}`;

					let params = {
						props: item,
						on: item.on
					};
					// Default
					if (!item.type || item.type === "expand") {
						params.scopedSlots = {
							default: scope => {
								// Column-slot
								let slot = this.$scopedSlots[`column-${item.prop}`];
								let newScope = {
									...scope,
									...item
								};

								let value = get(scope.row, item.prop);
								if (slot) {
									return slot({ scope: newScope });
								} else {
									if (item.render) {
										return item.render(scope);
									}
									// Formatter
									else if (item.formatter) {
										return item.formatter(
											newScope.row,
											newScope.column,
											newScope.row[item.prop],
											newScope.$index
										);
									}
									// Empty text
									else if (value === null) {
										return scope.emptyText;
									}
									// Value
									else {
										return value;
									}
								}
							},
							header: scope => {
								let slot = this.$scopedSlots[`header-${item.prop}`];
								if (slot) {
									return slot({ scope });
								} else {
									return scope.column.label;
								}
							}
						};
					}
					const children = item.children ? deep(item.children, key) : null;
					// console.log(children);
					return (
						<el-table-column key={`column-${key}`} align="center" {...params}>
							{children}
						</el-table-column>
					);
				});
			};
			return deep(this.columns, "0");
		},
		renderSlot(slot) {
			const h = this.$createElement;
			return h(
				"template",
				{
					slot
				},
				this.$slots[slot]
			);
		},
		onResize(h) {
			// this.clientHeight = 0;
			this.$nextTick(() => {
				this.clientHeight = h;
			});
		},
		clearSelection() {
			this.$refs.table.clearSelection();
		},
		toggleRowSelection(row, selected) {
			this.$refs.table.toggleRowSelection(row, selected);
		},
		toggleAllSelection() {
			this.$refs.table.toggleAllSelection();
		},
		toggleRowExpansion() {
			this.$refs.table.toggleRowExpansion();
		},
		setCurrentRow(row) {
			this.$refs.table.setCurrentRow(row);
		},
		clearSort() {
			this.$refs.table.clearSort();
		},
		clearFilter(columnKey) {
			this.$refs.table.clearFilter(columnKey);
		},
		doLayout() {
			this.$refs.table.doLayout();
		},
		sort(prop, order) {
			this.$refs.table.sort(prop, order);
		},
		sizeChange(v) {
			// console.log("sizeChange");

			this.pageSize = v;
			this.$emit("update:limit", v);
			this.$emit("limit-change", v);
			// if (this.resetPage) {
			// 	this.currentChange(1);
			// }
			this.paginationChange();
		},
		currentChange(v) {
			this.currentPage = v;
			this.$refs.table.bodyWrapper.scrollTop = 0;
			this.$emit("update:page", v);
			this.$emit("page-change", v);
			this.paginationChange();
		},
		paginationChange() {
			this.$emit("pagination", { limit: this.pageSize, page: this.currentPage });
		}
	}
};
</script>
<style lang="scss" scped>
.data-table {
	width: 100%;
	// height: 100%;
	// .el-table__body-wrapper {
	// 	// height: 100%;
	// }
}
.table-footer {
	position: relative;
	display: flex;
	justify-content: flex-end;
}
</style>
